package com.ashton;

import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public class ImageClass extends Component {
	private static final long serialVersionUID = 1L;
	BufferedImage img;
	BufferedImage sketch_img;
	int tile_width_num;
	int tile_height_num;
	HashMap<Point, Pixel> pixel_map=new HashMap<Point, Pixel>();
	List<Pixel> pixels_by_diff;
	int sleep_time=0;
//	String file_string="./Resources/morgan_freeman.jpg";
//	String file_string="./Resources/ashton2.jpg";
//	String file_string="./Resources/actors/lawrence.jpeg";

	String file_string="./Resources/rainbow_rose.jpg";
//	String file_string="./Resources/cup.png";
//	String file_string="./Resources/rainbow.png";
	double sketch_pixel_pct=.3;
	
	public ImageClass(){
		try{
			img= ImageIO.read(getClass().getResource(file_string));
//			img = (BufferedImage) new ImageIcon(getClass().getResource(file_string)).getImage();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
    
    List<Mosaic_Rect> set_tile_size(int tile_width_num_arg, int tile_height_num_arg){
    	tile_width_num=tile_width_num_arg;
    	tile_height_num=tile_height_num_arg;
    	int width=Math.round(img.getWidth()/tile_width_num);
    	int height=Math.round(img.getHeight()/tile_height_num);
    	List<Mosaic_Rect> rect_list=new ArrayList<Mosaic_Rect>();
		for (int w_i=0; w_i<tile_width_num; w_i++){
			for (int h_i=0; h_i<tile_height_num; h_i++){
				Mosaic_Rect m_r=new Mosaic_Rect(w_i*width, h_i*height, width, height);
				rect_list.add(m_r);
//				System.out.println(m_r.toString());				
			}
		}
		return rect_list;
    }
       
    void find_avg_colors(List<Mosaic_Rect> r){
		sketch_img= new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);

    	for (Mosaic_Rect rect:r){
    		rect.pixel_list=get_rgb_list(rect);
    		rect.avg_color=rect.find_average();
    		int[] rgb=new int[rect.width*rect.height];
    		Arrays.fill(rgb, rect.avg_color.getRGB());
    		sketch_img.setRGB(rect.x, rect.y, rect.width, rect.height, rgb, 0, rect.width);
    		repaint();
    	}
    }
    
    public List<Pixel> get_rgb_list(Mosaic_Rect rect){

    	List<Pixel> pixel_list=new ArrayList<Pixel>();
		for (int width_index=rect.x; width_index<rect.up_right_pt.x; width_index++){
			for (int height_index=rect.y; height_index<rect.low_right_pt.y; height_index++){
				Pixel pixel=new Pixel(width_index, height_index,
						img.getRGB(width_index, height_index));
//				p.print_pixel_info();
				pixel_list.add(pixel);
			}//end height_index for
		}//end width_index for
		rect.pixel_list=pixel_list;
    	return pixel_list;
    }
    
    //v2
    public HashMap<Point, Pixel> get_rgb_map(Mosaic_Rect rect){
    	int[] rgb_array=new int[rect.width*rect.height];
    	img.getRGB(rect.x, rect.y, rect.width, rect.height, rgb_array, 0, rect.width);
    	HashMap<Point, Pixel> h_m=new HashMap<Point, Pixel>();
		for (int width_index=rect.x; width_index<rect.up_right_pt.x; width_index++){
			for (int height_index=rect.y; height_index<rect.low_right_pt.y; height_index++){
				Pixel pixel=new Pixel(width_index, height_index,
						img.getRGB(width_index, height_index));
//				p.print_pixel_info();
				h_m.put(pixel.p, pixel);
			}//end height_index for
		}//end width_index for
    	return h_m;
    }
    
    
    public HashMap<Point, Pixel> get_rgb_map_with_diff(Mosaic_Rect rect){

		for (int width_index=rect.x; width_index<rect.up_right_pt.x; width_index++){
			for (int height_index=rect.y; height_index<rect.low_right_pt.y; height_index++){
				
				Pixel pixel=new Pixel(width_index, height_index,
						img.getRGB(width_index, height_index));
//				p.print_pixel_info();
				if (pixel.p.x>rect.x){
					Pixel p_2=rect.pixel_map.get(new Point(width_index-1, height_index));//left pixel
					pixel.hds=pixel.compare(p_2);//horizontal difference
				}if (pixel.p.y>rect.y){
					Pixel p_2=rect.pixel_map.get(new Point(width_index, height_index-1));//left pixel
					pixel.vds=pixel.compare(p_2);//vertical difference
				}if (pixel.p.y>rect.y && pixel.p.x>rect.x){
					Pixel p_2=rect.pixel_map.get(new Point(width_index-1, height_index-1));//left pixel
					pixel.ulds=pixel.compare(p_2);//upper left difference
				}
				rect.pixel_map.put(pixel.p, pixel);

				
			}//end height_index for
		}//end width_index for
    	return rect.pixel_map;
    }
	
	public void calc_diff_2(Pixel p_1){
		
	}
    
    //v1
	public HashMap<Point, Pixel> get_pixel_map_all_pixels(){
		return pixel_map=get_rgb_map(new Mosaic_Rect(0,0, img.getWidth(),img.getHeight()));
	}
	
	public void print_pixel_info(HashMap<Point, Pixel> h){
		for (Pixel p : h.values()){p.print_pixel_info();}

	}
	
	public void print_all_pixel_info(){
		for (Pixel p : pixel_map.values()){p.print_pixel_info();}
	}
	
	public void sort_pixels_diff(Mosaic_Rect rect){
		pixels_by_diff=new ArrayList<Pixel>(rect.pixel_map.values());
		
		Collections.sort(pixels_by_diff, diff_compare);
//		for (Pixel p : pixels_by_diff){
//			System.out.printf("hds %d, vds %d%n", p.hds, p.vds);
//		}
	}
	
	void create_sketch_image(){
		Mosaic_Rect whole_image_rect=new Mosaic_Rect(0, 0, img.getWidth(), img.getHeight());
		whole_image_rect.pixel_map=get_rgb_map_with_diff(whole_image_rect);
//		print_pixel_info(whole_image_rect.pixel_map);
//		set_pixels_all_diff();
		sort_pixels_diff(whole_image_rect);
		draw_sketch_image();
	}
	
	void draw_sketch_image(){
//		int t=(int) (pixels_by_diff.size()*(.9));
		sketch_img= new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
		List<Contrast_Layer> layer_list=new ArrayList<Contrast_Layer>();
		layer_list.add(new Contrast_Layer(Color.red, pixels_by_diff.size()-1, (int) (pixels_by_diff.size()*(.8))));
		layer_list.add(new Contrast_Layer(Color.orange, (int) (pixels_by_diff.size()*(.80)-1),(int) (pixels_by_diff.size()*(.6))));
		layer_list.add(new Contrast_Layer(Color.yellow.brighter(), (int) (pixels_by_diff.size()*(.6)-1),(int) (pixels_by_diff.size()*(.5))));
		layer_list.add(new Contrast_Layer(Color.white, (int) (pixels_by_diff.size()*(.5))-1, 0));
		
		for (Contrast_Layer c : layer_list){
			for (int k=c.upper_bound; k>c.lower_bound; k--){
				sketch_img.setRGB(pixels_by_diff.get(k).p.x, pixels_by_diff.get(k).p.y, c.color.getRGB());
				try {
					Thread.sleep(sleep_time);
					repaint();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	
	}

	void convertToGray(){
		//create same size gray image
		sketch_img= new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
		
		ColorConvertOp op = new ColorConvertOp(
	              img.getColorModel().getColorSpace(),
	              sketch_img.getColorModel().getColorSpace(),null);
	    sketch_img = op.filter(img, sketch_img);
	             
	}	
	
    public void paint(Graphics g) {
//        g.drawImage(img, 0, 0, null);
        g.drawImage(sketch_img, img.getWidth(), 0, null);
    }
    
	Comparator<Pixel> diff_compare=new Comparator<Pixel>() {
		public int compare(Pixel p_1, Pixel p_2){

			return (p_1.get_largest_diff_sum().compareTo(p_2.get_largest_diff_sum()));

		}
	};
}



